package it.eng.area118.mdogpscollector.service;

import it.eng.area118.mdocommon.android.util.StringUtils;
import it.eng.area118.mdogpscollector.db.DbManager;
import it.eng.area118.mdogpscollector.db.Item;
import it.eng.area118.mdogpscollector.model.PerstRootBean;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.garret.perst.Index;
import org.garret.perst.Storage;

import android.util.Log;

public abstract class AbstractStoreService<E extends Item> implements StoreService<E> {

	private DbManager manager;
	private IndexLookupService service;
	private Storage db;

	public AbstractStoreService(String file, Class<E> clazz) {
		db = DbManager.getDb(file);
		manager = new DbManager(db);
		PerstRootBean root = (PerstRootBean) db.getRoot();
		Index i = root.getIndex(clazz, db, false);
		service = new IndexLookupService(i, clazz, db);
	}

	public E saveOrUpdate(E e, Class<E> clazz) {
		E fromDb = service.getItem(e.getItemKey());
		if (fromDb == null) {
			db.storeObject(e);
			manager.storeObjectWithIndex(clazz, e);
			db.commit();
			Log.i("saveOrUpdate", "object save item key is: " + e.getItemKey());
			return service.getItem(e.getItemKey());
		} else {
			manager.removeIndex(clazz, fromDb);
			update(e, fromDb);
			db.storeObject(fromDb);
			manager.storeObjectWithIndex(clazz, fromDb);
			db.commit();
		}

		return fromDb;
	}

	//
	// private void update(E detachedObj, E fromDb) {
	// updateSmipleField("type", detachedObj, fromDb);
	// updateSmipleField("direction", detachedObj, fromDb);
	// }

	public abstract void update(E detachedObj, E fromDb);

	protected void updateSmipleField(String name, E detachedObj, E fromDb) {
		String sourceValue = "";
		String destValue = "";
		Class<E> sourceClass = (Class<E>) detachedObj.getClass();
		try {

			Field field = sourceClass.getDeclaredField(name);

			try {
				Method met = sourceClass.getMethod("get" + upperCaseFirstChar(name), new Class[] {});
				sourceValue = (String) met.invoke(detachedObj, new Object[] {});
				System.out.println("Source Value for " + name + ": " + sourceValue);
			} catch (Exception e) {

			}

			try {
				Method met = sourceClass.getMethod("get" + upperCaseFirstChar(name), new Class[] {});
				destValue = (String) met.invoke(fromDb, new Object[] {});
				System.out.println("Dest value for " + name + ": " + destValue);
			} catch (Exception e) {

			}

		} catch (SecurityException e) {

		} catch (NoSuchFieldException e) {

		}

		/* update only if is filled the field of the detached object */
		if (!StringUtils.isEmpty(sourceValue)) {
			try {
				Method met = sourceClass.getMethod("set" + upperCaseFirstChar(name), new Class[] { String.class });
				met.invoke(fromDb, new Object[] { sourceValue });
			} catch (SecurityException e1) {

			} catch (NoSuchMethodException e1) {

			} catch (IllegalArgumentException e) {

			} catch (IllegalAccessException e) {

			} catch (InvocationTargetException e) {

			}
		}
	}

	private static String upperCaseFirstChar(String s) {
		String first = new String(s).substring(0, 1).toUpperCase();
		String other = new String(s).substring(1, s.length()).toLowerCase();
		return first + other;
	}

}
